package com.ukefu.webim.util.weixin.handler;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.Map;

import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.ukefu.core.UKDataContext;
import com.ukefu.util.UKTools;
import com.ukefu.util.WechatUtils;
import com.ukefu.util.client.NettyClients;
import com.ukefu.util.client.UserClient;
import com.ukefu.webim.service.cache.CacheHelper;
import com.ukefu.webim.service.repository.AgentUserTaskRepository;
import com.ukefu.webim.service.repository.ChatMessageRepository;
import com.ukefu.webim.service.repository.SNSAccountRepository;
import com.ukefu.webim.util.AMRConvert;
import com.ukefu.webim.util.UKWeiXinTools;
import com.ukefu.webim.util.server.message.ChatMessage;
import com.ukefu.webim.util.weixin.config.WechatMpConfiguration;
import com.ukefu.webim.util.weixin.config.WeiXinConfiguration;
import com.ukefu.webim.web.model.AgentUser;
import com.ukefu.webim.web.model.AgentUserTask;
import com.ukefu.webim.web.model.Instruction;
import com.ukefu.webim.web.model.SNSAccount;
import com.ukefu.webim.web.model.SystemConfig;
import com.ukefu.webim.web.model.WeiXinUser;

import it.sauronsoftware.jave.EncoderException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;

@Component
public class MsgHandler extends AbstractHandler {
	
	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private SNSAccountRepository snsAccountRes ;
	
	@Autowired
	private ChatMessageRepository chatMessageRes ;
	
	@Autowired
	private AgentUserTaskRepository agentUserTaskRes ;
	
	@Value("${web.upload-path}")
    private String path;
	
    @SuppressWarnings("unchecked")
	@Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
            Map<String, Object> context, WxMpService weixinService,
            WxSessionManager sessionManager) throws WxErrorException {
    	WxMpXmlOutMessage out = null ;
    	SNSAccount snsAccount ;
		String key = wxMessage.getFromUser();
		if (context != null && StringUtils.isNotBlank((String)context.get("snsid"))) {
			key = key + "_" + context.get("snsid");
		}

    	WeiXinUser user = (WeiXinUser) UserClient.getUserClientMap().get(key) ;
    	SystemConfig systemConfig = (SystemConfig) CacheHelper.getSystemCacheBean().getCacheObject("systemConfig", UKDataContext.SYSTEM_ORGI);
		if(systemConfig!=null && "debug".equals(systemConfig.getLoglevel())){
			this.logger.info("\n接收到来自用户的服务请求：[{},{} , {} , {}]", wxMessage.getFromUser() , user , wxMessage.getFromUser() , UserClient.getUserClientMap().containsKey(key));
		}
    	if(user!=null){
    		wxMessage.setContent(WechatUtils.wechatToUCKeFuface(wxMessage.getContent()));
    		WeiXinConfiguration weiXinConfig = WechatMpConfiguration.getInstance().getConfiguration(user.getSnsid()) ;
    		if(weiXinConfig!=null){
    			snsAccount = weiXinConfig.getSnsAccount() ;
    		}else{
    			snsAccount = snsAccountRes.findBySnsidAndOrgi(user.getSnsid() , user.getOrgi()) ;
    		}
    		/**
    		 * 当前微信 客户接入人工坐席条件：
    		 * 1、已经在 坐席对话列表中
    		 * 2、公众号启用了人工坐席
    		 * 3、当前用户输入了接入人工坐席的指令 或 公众号设置的 所有对话都转接人工坐席
    		 */
    		if(snsAccount != null ){
	    		if(CacheHelper.getAgentUserCacheBean().getCacheObject(user.getOpenid(), user.getOrgi()) == null){
		    		String topic = UKTools.getTopic(user.getSnsid(), wxMessage.getMsgType(), wxMessage.getEvent() , wxMessage.getEventKey(), wxMessage.getContent()) ;
		    		Collection<Instruction> insList = (Collection<Instruction>) CacheHelper.getIMRCacheBean().getCacheObject(topic, user.getOrgi());
		    		if(insList==null || insList.size() == 0){
		    			topic = UKTools.getTopic(user.getSnsid(), wxMessage.getMsgType(), wxMessage.getEvent()) ;
			    		insList = (Collection<Instruction>) CacheHelper.getIMRCacheBean().getCacheObject(topic, user.getOrgi());
		    		}
		    		if(insList!=null && insList.size()>0){
		    			for(Instruction ins : insList){
		    				try {
								out = UKWeiXinTools.processInstruction(ins, user, wxMessage, weixinService,snsAccount.isAgent()) ;
							} catch (Exception e) {
								e.printStackTrace();
							}
		    			}
		    		}
	    		}
	    		/**
	    		 * 再次获取agentUser信息
	    		 */
	    		AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(user.getOpenid(), user.getOrgi());
	    		if(systemConfig!=null && "debug".equals(systemConfig.getLoglevel())){
    				this.logger.info("\n接收到来自用户的消息：[{},{}]", user.getNickname() , agentUser );
    			}
    			ChatMessage data = new ChatMessage() ;
    			data.setAppid(user.getSnsid());
    			data.setUserid(user.getOpenid());
    			data.setType("message");
    			data.setUsession("");
    			data.setOrgi(user.getOrgi());

    			if(UKDataContext.MediaTypeEnum.IMAGE.toString().equals(wxMessage.getMsgType())){
    				try {
    					File mediaFile = weiXinConfig.getService().getMaterialService().mediaDownload(wxMessage.getMediaId()) ;
    					String fileName = "weixin/image/"+wxMessage.getMediaId()+"_original" ;
    					File file =  new File(path ,fileName) ;
    					if(file.getParentFile().exists()){
    						file.getParentFile().mkdirs() ;
    					}
    					FileUtils.copyFile(mediaFile, file);
    					String thumbnailsFileName = "weixin/image/"+wxMessage.getMediaId() ;
    					UKTools.processImage(new File(path , thumbnailsFileName), file) ;

    					data.setMessage("/res/image.html?id="+thumbnailsFileName);
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}else if(UKDataContext.MediaTypeEnum.EVENT.toString().equals(wxMessage.getMsgType())){
    				data.setMessage(wxMessage.getEventKey());
    				data.setType("event");
    			}else if(UKDataContext.MediaTypeEnum.VOICE.toString().equals(wxMessage.getMsgType())){
    				data.setMediaid(wxMessage.getMediaId());
    				if(!StringUtils.isBlank(wxMessage.getRecognition())){
    					data.setExpmsg(wxMessage.getRecognition());
    				}
    				File mediaFile = weiXinConfig.getService().getMaterialService().mediaDownload(wxMessage.getMediaId()) ;
    				String fileName = "weixin/voice/"+wxMessage.getMediaId()+".mp3" ;
    				File file = new File(path ,fileName) ;
    				if(file.getParentFile().exists()){
    					file.getParentFile().mkdirs() ;
    				}
    				try {
    					//							FileUtils.copyDirectory(mediaFile, new File(path ,fileName));
    					AMRConvert.mp3(mediaFile, file);
    				} catch (EncoderException e) {
    					e.printStackTrace();
    				} catch(Exception ex){
    					ex.printStackTrace();
    				}finally{
    					int duration = AMRConvert.getMp3TrackLength(file) ;
    					data.setDuration(duration);
    					mediaFile.deleteOnExit();
    				}
    				data.setMessage("/res/voice.html?id="+fileName);
    			}else if(UKDataContext.MediaTypeEnum.LOCATION.toString().equals(wxMessage.getMsgType())){
    				data.setLocx(String.valueOf(wxMessage.getLocationX()));
    				data.setLocy(String.valueOf(wxMessage.getLocationY()))	;
    				data.setScale(String.valueOf(wxMessage.getScale()));
    				data.setMessage(wxMessage.getLabel());
    			}else{
    				data.setMessage(wxMessage.getContent());
    			}
    			data.setMsgtype(wxMessage.getMsgType());
    			data.setCalltype(UKDataContext.CallTypeEnum.IN.toString());
    			data.setChannel(UKDataContext.ChannelTypeEnum.WEBIM.toString());
    			data.setId(UKTools.getUUID());
    			
    	    	if(agentUser!=null){
    	    		data.setUserid(agentUser.getUserid());
    	    		data.setUsername(agentUser.getUsername());
    	    		data.setTouser(agentUser.getAgentno());

    	    		data.setAgentuser(agentUser.getId());

    	    		data.setAgentserviceid(agentUser.getAgentserviceid());
    	    		
    	    		data.setHeadimgurl(agentUser.getHeadimgurl());
    	    		
    	    		data.setUsername(agentUser.getUsername());
    	    		data.setUsession(agentUser.getUserid());				//agentUser作为 session id
    	    		data.setContextid(agentUser.getContextid());
    	    		if(!StringUtils.isBlank(agentUser.getAgentno())){
    	    			data.setTouser(agentUser.getAgentno());
    	    		}
    	    		
    	    		if(data.getType()!=null && data.getType().equals("message")){
    		    		AgentUserTask agentUserTask = agentUserTaskRes.getOne(agentUser.getId()) ;
    		    		agentUserTask.setLastmessage(new Date());
    		    		agentUserTask.setWarnings("0");
    		    		agentUserTask.setWarningtime(null);
    		    		if(data.getMessage()!=null){
    		    			agentUserTask.setLastmsg(data.getMessage().length() > 100 ? data.getMessage().substring(0 , 100) : data.getMessage());
    		    		}else{
    		    			agentUserTask.setLastmsg("");
    		    		}
    		    		agentUserTask.setUserasks(agentUserTask.getUserasks()+1);
    		    		agentUserTask.setTokenum(agentUserTask.getTokenum()+1);
    		    		data.setTokenum(agentUserTask.getTokenum());
    		    		agentUserTaskRes.save(agentUserTask) ;
    	    		}
    	    		if(agentUser!=null && !StringUtils.isBlank(agentUser.getAgentno()) && UKDataContext.MessageTypeEnum.MESSAGE.toString().equals(data.getType())){
    	        		NettyClients.getInstance().sendAgentEventMessage(agentUser.getAgentno(), UKDataContext.MessageTypeEnum.MESSAGE.toString(), data);
    	        	}
    			}else {
    				data.setUserid(user.getOpenid());
    	    		data.setUsername(user.getNickname());

    	    		data.setAgentuser(user.getOpenid());

    	    		data.setHeadimgurl(user.getHeadimgurl());
    	    		
    	    		data.setUsession(user.getOpenid());				//agentUser作为 session id
    			}
    	    	/**
	    		 * 保存消息
	    		 */
	    		if(UKDataContext.MessageTypeEnum.MESSAGE.toString().equals(data.getType())){
	    			chatMessageRes.save(data) ;
	    		}
    		}
    	}
        return  out;
    }
}
